package gr.atc.epart.googlewrapper.calendar;

import gr.atc.epart.HttpConnector;
import gr.atc.epart.googlewrapper.GoogleServiceCallbackType;
import gr.atc.epart.googlewrapper.accounts.GoogleAccountManager;

import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringBufferInputStream;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.List;

import org.apache.http.Header;
import org.apache.http.entity.StringEntity;
import org.apache.http.message.BasicHeader;
import org.apache.http.protocol.HTTP;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import android.app.Activity;
import android.os.Handler;
import android.os.Message;
import android.text.style.ForegroundColorSpan;
import android.util.Log;

import com.google.gdata.client.calendar.CalendarService;
import com.google.gdata.data.calendar.CalendarEntry;
import com.google.gdata.data.calendar.CalendarFeed;

public class Calendar 
{
	 private GoogleAccountManager	_manager; 
	 private Activity 				_activity;
	 private Handler 				_ownerCallback;
	 private String  				_authToken;
	 private String 					_username;
	 private String 					_userpwd;
	 
	 
	 //
	 // used to receive callbacks from low level asynchronous operations  
	 //
	 private Handler _messageHandler = new Handler() 
	  {
	      public void handleMessage(Message msg) 
	      {  
	          switch(msg.what) 
	          {
	        	  case GoogleServiceCallbackType.AuthTokenReceived:
	        		  
	        		  _authToken = msg.getData().getString("AUTHTOKEN");
	        		  _ownerCallback.sendEmptyMessage(GoogleServiceCallbackType.CalendarServiceIsReady);
	        		  
	        		  break;
	        		  
	        	  case GoogleServiceCallbackType.UserAuthenticationRequired:
	        		  _ownerCallback.sendEmptyMessage(GoogleServiceCallbackType.UserAuthenticationRequired);
	        		  break;

	        	  case GoogleServiceCallbackType.CalendarFeedsReceived:
	        		  // calendar feeds received...
	        		  String calendarFeeds = msg.getData().getString("RESPONSE");
	        		  
					  try
					  {
						  StringReader calendarFeedsReader = new StringReader(calendarFeeds); 
						  calendarFeedsReader.reset();
						  parseCalendarFeeds(calendarFeedsReader);
						  
					  }
					  catch (IOException e)
					  {
						// TODO Auto-generated catch block
						e.printStackTrace();
				 	  }
	        		  
	        		  // notify the caller that the results are ready
	        		  _ownerCallback.sendEmptyMessage(GoogleServiceCallbackType.CalendarFeedsReceived);
	        		  break;

	        	  case GoogleServiceCallbackType.CalendarFeedEventsReceived:
	        		  // calendar feeds received...
	        		  String calendarEventFeeds = msg.getData().getString("RESPONSE");
	        		  
					  try
					  {
						  StringReader calendarEventFeedsReader = new StringReader(calendarEventFeeds); 
						  calendarEventFeedsReader.reset();
						  parseCalendarFeedEvents(calendarEventFeedsReader);
					  }
					  catch (IOException e)
					  {
						// TODO Auto-generated catch block
						e.printStackTrace();
				 	  }
	        		  
	        		  // notify the caller that the results are ready
	        		  _ownerCallback.sendEmptyMessage(GoogleServiceCallbackType.CalendarFeedEventsReceived);
	        		  break;

	        	  case GoogleServiceCallbackType.CalendarEventAdded:

	        		  // calendar feeds received...
	        		  String calendarEventAddResponse = msg.getData().getString("RESPONSE");

	        		  // notify the caller that the results are ready
	        		  _ownerCallback.sendEmptyMessage(GoogleServiceCallbackType.CalendarEventAdded);

	        		  break;
	        		  
	        	  case GoogleServiceCallbackType.OperationError:
	        		  _ownerCallback.sendMessage(msg);
	        		  break;
	          }
	      }

		
	  };
		 
	 public Calendar(Activity activity,Handler ownerCallback)
	 {
		    _activity = activity;
		 	_ownerCallback = ownerCallback;
		 	
		    _manager = new GoogleAccountManager(_activity,_messageHandler);
	 }
	 
	 public void authenticate()
	 {
		    _manager.getCalendarToken();
	 }
	 
	 public void retrieveCalendars()
	 {
		  
			HttpConnector connector = new HttpConnector();
			String sessionUrl = "http://www.google.com/calendar/feeds/default/allcalendars/full";
			//String sessionUrl = "http://www.google.com/calendar/feeds/default/owncalendars/full";
			
			Header[] headers = new Header[1];
			headers[0] = new BasicHeader("Authorization", "GoogleLogin auth="+_authToken);
			//
			// "Try to receive the calendars and notify me when it is OK"
			//
			
			connector.executeGetRequestAsync(sessionUrl, GoogleServiceCallbackType.CalendarFeedsReceived,_messageHandler,headers);
	}
	 
	 public void retrieveEventsForFeed(String feedId)
	 {
			HttpConnector connector = new HttpConnector();
			String sessionUrl = "http://www.google.com/calendar/feeds/"+feedId+"/private/full";
			//String sessionUrl = "http://www.google.com/calendar/feeds/default/owncalendars/full";
			
			Header[] headers = new Header[1];
			headers[0] = new BasicHeader("Authorization", "GoogleLogin auth="+_authToken);
			//
			// "Try to receive the calendars and notify me when it is OK"
			//
			connector.executeGetRequestAsync(sessionUrl, GoogleServiceCallbackType.CalendarFeedEventsReceived,_messageHandler,headers);
	}

	 public void addEventToFeed(String feedId)
	 {
						
		try
		{
			HttpConnector connector = new HttpConnector();
			String sessionUrl = "http://www.google.com/calendar/feeds/"+feedId+"/private/full";

			String dummyEvent = "<entry xmlns=\'http://www.w3.org/2005/Atom\' xmlns:gd=\'http://schemas.google.com/g/2005\'> <category scheme=\'http://schemas.google.com/g/2005#kind\' term=\'http://schemas.google.com/g/2005#event\'> </category>  <title type=\'text\'>Tennis with Beth</title>  <content type=\'text\'>Meet for a quick lesson.</content> <gd:transparency value=\'http://schemas.google.com/g/2005#event.opaque\'> </gd:transparency> <gd:eventStatus value=\'http://schemas.google.com/g/2005#event.confirmed\'>  </gd:eventStatus>  <gd:where valueString=\'Rolling Lawn Courts\'> </gd:where> <gd:when startTime=\'2010-07-17T15:00:00.000Z\' endTime=\'2010-07-17T17:00:00.000Z\'> </gd:when> </entry>"; 
			StringEntity  eventData = new StringEntity(dummyEvent,"UTF-8");
			
			eventData.setContentType("text/xml");

			Header[] headers = new Header[2];
			headers[0] = new BasicHeader("Content-Type", "application/atom+xml");
			headers[1] = new BasicHeader("Authorization", "GoogleLogin auth="+_authToken);
			
			connector.executePostRequestAsync(sessionUrl, GoogleServiceCallbackType.CalendarEventAdded, eventData, _messageHandler, headers);
			
		} catch (UnsupportedEncodingException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		 
		 
	 }
	 
	 /*
	private void performClientLogin()
	{
		HttpConnector connector = new HttpConnector();
		String sessionUrl = "https://www.google.com/accounts/ClientLogin";

		HashMap<String, String> parameters = new HashMap<String, String>();
		parameters.put("Email","atcmobileiphone@gmail.com"); 
		parameters.put("Passwd","atcmobileiphone");
		parameters.put("source","atc-eparticipation-1.0");
		parameters.put("service","cl");
		parameters.put("accountType","GOOGLE");
		
		connector.executePostRequestAsync(sessionUrl, GoogleServiceCallbackType.CalendarFeedsReceived, parameters, _messageHandler);

	}
	 */
	 
	private void parseCalendarFeeds(Reader calendarFeeds)
	{
		 
		try
		{
			//
			// idea from here
			// http://zonakusu.blogspot.com/2009/08/xpath-in-android-dom4j-jaxen.html
			//
			SAXReader reader = new SAXReader();
			Document feedsDocument = reader.read(calendarFeeds);
			//feedsDocument.
			
			Element rootFeed = (Element) feedsDocument.selectSingleNode ("/feed");

			// get the namespaces for later Xpath 
			String rootXmlNsURI =  rootFeed.getNamespaceURI();
			String gCalNameSpace = rootFeed.getNamespaceForPrefix("gCal").getURI();
			//String openSearchNameSpace = rootFeed.getNamespaceForPrefix("openSearch").getURI();
			
			feedsDocument.getRootElement().add(DocumentHelper.createNamespace("ns",rootXmlNsURI));
			feedsDocument.getRootElement().add(DocumentHelper.createNamespace("gcal",gCalNameSpace));
			
			List<Element> feedNodes = feedsDocument.selectNodes("//ns:feed/ns:entry");
			for (Element feed:feedNodes)
			{
				parseFeed(feed,gCalNameSpace);
			}
			
		} catch (DocumentException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	private void parseFeed(Element feed,String ns )
	{
		try
		{
			String feedTitle = feed.elementText("title");
			String authorName = feed.selectSingleNode("ns:author/ns:name").getStringValue();
			// not always present...
			//String authorEmail = feed.selectSingleNode("ns:author/ns:email").getText();

			List<Element> linkNodes = feed.selectNodes("ns:link");
			for (Element link:linkNodes)
			{
				String rel  = link.attributeValue("rel");
				String type = link.attributeValue("type");
				String href = link.attributeValue("href");

				Log.i("feed link:rel" , rel);
				Log.i("feed link:type", type);
				Log.i("feed link:href", href);
			}
		}
		catch (NullPointerException e)
		{

		}

	}
	
	private void parseCalendarFeedEvents(StringReader calendarEventFeedsReader)
	{
		try
		{
			SAXReader reader = new SAXReader();
			Document feedEventsDocument = reader.read(calendarEventFeedsReader);
			
			Element rootFeed = (Element) feedEventsDocument.selectSingleNode ("/feed");

			// get the namespaces for later Xpath 
			String rootXmlNsURI =  rootFeed.getNamespaceURI();
			String gCalNameSpace = rootFeed.getNamespaceForPrefix("gCal").getURI();
			String gdNameSpace = rootFeed.getNamespaceForPrefix("gd").getURI();
			//String openSearchNameSpace = rootFeed.getNamespaceForPrefix("openSearch").getURI();
			
			feedEventsDocument.getRootElement().add(DocumentHelper.createNamespace("ns",rootXmlNsURI));
			feedEventsDocument.getRootElement().add(DocumentHelper.createNamespace("gcal",gCalNameSpace));
			feedEventsDocument.getRootElement().add(DocumentHelper.createNamespace("gd",gdNameSpace));
			
			List<Element> feedEventsNodes = feedEventsDocument.selectNodes("//ns:feed/ns:entry");
			for (Element feed:feedEventsNodes)
			{
				parseFeedEvent(feed,gCalNameSpace);
			}
			
		} catch (DocumentException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
	}

	private void parseFeedEvent(Element feed, String calNameSpace)
	{
		
		try
		{
			String eventTitle = feed.elementText("title");
			String eventDescription = feed.elementText("content");
			
			String authorName = feed.selectSingleNode("ns:author/ns:name").getStringValue();

			// not always present...
			//String authorEmail = feed.selectSingleNode("ns:author/ns:email").getText();
			Element whereNode = (Element)feed.selectSingleNode("gd:where");
			String eventWhere = whereNode.attributeValue("valueString"); 

			Element whoNode = (Element)feed.selectSingleNode("gd:who");
			String eventWhoEmail = whoNode.attributeValue("email");
			String eventWhoName = whoNode.attributeValue("valueString");

			Element whenNode = (Element)feed.selectSingleNode("gd:when");
			String eventWhenStart = whenNode.attributeValue("startTime");
			String eventWhenFinish = whenNode.attributeValue("endTime");
			
			List<Element> notificationsNode = (List<Element>)whenNode.selectNodes("gd:reminder");
			for (Element notification:notificationsNode)
			{
				String method = notification.attributeValue("method");
				String minutesBefore = notification.attributeValue("minutes");
			}
			
			Element anyoneCanAddSelfNode =  (Element)feed.selectSingleNode("gcal:anyoneCanAddSelf");
			boolean anyoneCanAddSelf = Boolean.parseBoolean(anyoneCanAddSelfNode.attributeValue("value"));

			
			Element guestsCanInviteOthersNode =  (Element)feed.selectSingleNode("gcal:guestsCanInviteOthers");
			boolean guestsCanInviteOthers = Boolean.parseBoolean(guestsCanInviteOthersNode.attributeValue("value"));

			Element guestsCanModifyNode =  (Element)feed.selectSingleNode("gcal:guestsCanModify");
			boolean guestsCanModify = Boolean.parseBoolean(guestsCanModifyNode.attributeValue("value"));

			Element guestsCanSeeGuestsNode =  (Element)feed.selectSingleNode("gcal:guestsCanSeeGuests");
			boolean guestsCanSeeGuests = Boolean.parseBoolean(guestsCanSeeGuestsNode.attributeValue("value"));

			Element uidNode =  (Element)feed.selectSingleNode("gcal:uid");
			String uid = uidNode.attributeValue("value");

			List<Element> linkNodes = feed.selectNodes("ns:link");
			for (Element link:linkNodes)
			{
				String rel  = link.attributeValue("rel");
				String type = link.attributeValue("type");
				String href = link.attributeValue("href");

				Log.i("feed link:rel" , rel);
				Log.i("feed link:type", type);
				Log.i("feed link:href", href);
			}
		}
		catch (NullPointerException e)
		{

		}
	}



}
